﻿using System;
using System.Collections.Generic;
using System.Linq;
using DevelopTool.Bll.LocalDbBlls;
using DevelopTool.Bll.SchedulerBlls.Jobs;
using DevelopTool.Common;
using DevelopTool.Model.CommonModels;
using DevelopTool.Model.Enums;
using DevelopTool.Model.SchedulerModels;
using LiteDB;
using Sunny.UI;

namespace DevelopTool.Bll.SchedulerBlls
{
    /// <summary>
    /// 定时任务操作
    /// </summary>
    public class SchedulerBll : BaseBll
    {
        public SchedulerBll()
        {
            using (var db = new LiteDatabase(LiteDbContext.ConnectionString))
            {
                var col = db.GetCollection<Scheduler>();
                col.EnsureIndex(x => x.NodeName);
                col.EnsureIndex(x => x.NodePid);
                col.EnsureIndex(x => x.NodeType);
                col.EnsureIndex(x => x.CreateTime);
                col.EnsureIndex(x => x.Id);
            }
        }

        /// <summary>
        /// 获取定时任务集合
        /// </summary>
        /// <param name="nodeType"></param>
        /// <returns></returns>
        public List<Scheduler> GetList(MenuNodeType nodeType = MenuNodeType.Unknown)
        {
            using (var db = new LiteDatabase(LiteDbContext.ConnectionString))
            {
                var models = db.GetCollection<Scheduler>().FindAll();

                if(nodeType != MenuNodeType.Unknown)
                {
                    models = models.Where(it => it.NodeType == nodeType);
                }

                return models.OrderByDescending(it => it.CreateTime).ToList();
            }
        }






        /// <summary>
        /// 根据id获取定时任务
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Scheduler GetById(int id)
        {
            using (var db = new LiteDatabase(LiteDbContext.ConnectionString))
            {
                var col = db.GetCollection<Scheduler>();


                return col.FindById(id);
            }
        }


        /// <summary>
        /// 保存定时任务
        /// </summary>
        /// <param name="scheduler"></param>
        /// <returns></returns>
        public Scheduler Save(Scheduler scheduler)
        {
            using (var db = new LiteDatabase(LiteDbContext.ConnectionString))
            {
                var col = db.GetCollection<Scheduler>();

                scheduler.UpdateTime = DateTime.Now;
                col.Upsert(scheduler);

                return col.FindById(scheduler.Id);
            }
        }


        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool Delete(int id)
        {
            using (var db = new LiteDatabase(LiteDbContext.ConnectionString))
            {
                var schedulerCol = db.GetCollection<Scheduler>();
                var scheduler = schedulerCol.FindById(id);

                //查询此定时任务是否有子节点，若有子节点，则不删除。
                if (schedulerCol.Exists(it => it.NodePid == scheduler.Id)) return false;


                //删除对应的任务类型

                if (scheduler.SchedulerType == "Sql")//sql
                {
                    var task = db.GetCollection<Scheduler_Sql>();
                    task.Delete(it => it.SchedulerId == scheduler.Id);
                }
                else if (scheduler.SchedulerType == "代码")//代码
                {

                }

                //删除任务日志
                var log = db.GetCollection<SchedulerLog>();
                log.Delete(it => it.SchedulerId == scheduler.Id);


                //删除定时任务
                var result = schedulerCol.Delete(scheduler.Id);

                return result;
            }
        }




        /// <summary>
        /// 启动标记为运行的定时任务，用于程序启动时调用
        /// </summary>
        /// <returns></returns>
        public void StartJob()
        {
            using (var db = new LiteDatabase(LiteDbContext.ConnectionString))
            {
                var col = db.GetCollection<Scheduler>();
                var list = col.Find(it => it.NodeType == MenuNodeType.Node && it.IsRun && !string.IsNullOrEmpty(it.Cron)).ToList();

                foreach (Scheduler scheduler in list)
                {
                    SchedulerRun(scheduler);
                }
            }
        }


        /// <summary>
        /// 任务是否正在运行
        /// </summary>
        /// <param name="scheduler"></param>
        /// <returns></returns>
        public bool IsRun(Scheduler scheduler)
        {
            return QuartzHelper.IsRun(scheduler.Id.ToString(), scheduler.SchedulerType.ToString());
        }


        /// <summary>
        /// 运行定时任务
        /// </summary>
        /// <param name="scheduler"></param>
        /// <returns></returns>
        public Tuple<bool, string> SchedulerRun(Scheduler scheduler)
        {
            //如果任务正在运行，那就删除重新添加
            if (IsRun(scheduler))
            {
                QuartzHelper.DeleteJob(scheduler.Id.ToString(), scheduler.SchedulerType.ToString());
            }

            Type type = null;
            if (scheduler.SchedulerType == "Sql")
            {
                type = typeof(SqlJob);//sql任务
            }
            else if (scheduler.SchedulerType == "代码")
            {
                type = typeof(CodeJob);//代码任务
            }

            Dictionary<string, object> paramDic = new Dictionary<string, object>
                {
                    { "scheduler", scheduler }//任务参数，可以添加多个
                };
            QuartzHelper.AddCronTriggerJob(type, scheduler.Id.ToString(), scheduler.SchedulerType.ToString(), scheduler.Cron, scheduler.StratTime, scheduler.EndTime, paramDic);

            return new Tuple<bool, string>(true, "任务启动成功");
        }


        /// <summary>
        /// 停止定时任务
        /// </summary>
        /// <param name="scheduler"></param>
        /// <returns></returns>
        public Tuple<bool, string> SchedulerStop(Scheduler scheduler)
        {
            bool deleteResult = QuartzHelper.DeleteJob(scheduler.Id.ToString(), scheduler.SchedulerType.ToString());
            return new Tuple<bool, string>(deleteResult, "任务停止成功");
        }

        public void SetRemark(int id,string remark)
        {
            using(var db = new LiteDatabase(LiteDbContext.ConnectionString))
            {
                var col = db.GetCollection<Scheduler>();

                var model = col.FindOne(it => it.Id == id);

                model.Remark = remark;
                model.UpdateTime = DateTime.Now;

                col.Update(model);
            }
        }

        public ManageMenu Get(int id)
        {
            using(var db = new LiteDatabase(LiteDbContext.ConnectionString))
            {
                return db.GetCollection<Scheduler>().FindOne(it => it.Id == id);
            }
        }
    }
}
